import type { ActionType, ProColumns } from '@ant-design/pro-table';
import { Button, Checkbox, Menu, Popconfirm, Typography, message, Tag, Space, Popover } from 'antd';
import { FieldTimeOutlined, RocketOutlined } from '@ant-design/icons';
import React, { useEffect, useRef, useState } from 'react';
import {
  getApiPermissionCheck as checkPermissionIsInit,
  getApiPermissionConfigureByKey as getPermissionConfigure,
  postApiPermissionReleaseConfigure as releaseConfigure,
  getApiPermissionResources as getPermissionResource
} from '@/services/furion-cms/permission'

import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
import { EditableProTable } from '@ant-design/pro-table';
import { PageContainer } from '@ant-design/pro-layout';
import PermissionRoutes from '../../config/permission';
import moment from 'moment';
import { useIntl } from 'umi';
import PermissionsDefinition from '@/permissionsDefinition';
import styles from './PermissionConfig.less';

const { Text } = Typography;

type PermissionMenu = {
  code?: string;
  name?: string;
  path?: string;
  icon?: string;
  authority?: string[];
  routes?: PermissionMenu[];
  hideInMenu?: boolean;
}

let initPermissionData: API.PermissionConfigReleaseDto[] = [];
let hasEditable = false;
const localStorageAutoSaveKey = "permissionConfigAutoSave";
const localStoragePermissionConfigKey = "localSavePermissionConfig";
const localStoragePermissionConfigSaveTimeKey = "localSavePermissionConfigLastSaveTime";

const PermissionConfig: React.FC = () => {

  const actionRef = useRef<ActionType>();
  /**
   * @en-US International configuration
   * @zh-CN 国际化配置
   * */
  const intl = useIntl();
  const [permissionIsInit, setPermissionIsInit] = useState<boolean>(false);

  const defaultAutoSaveState: boolean = localStorage.getItem(localStorageAutoSaveKey) === 'true';
  const defaultLocalPermissionConfig = defaultAutoSaveState ? JSON.parse(localStorage.getItem(localStoragePermissionConfigKey) || "[]") : [];

  console.log('init', defaultLocalPermissionConfig);
  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  const [localPermissionConfig, setLocalPermissionConfig] = useState<API.PermissionConfigReleaseDto[]>(defaultLocalPermissionConfig);
  const [remotePermissionConfig, setRemotePermissionConfig] = useState<API.PermissionConfigDto[]>([]);
  const [activeMenuItem, setActiveMenuItem] = useState<{ code: string; name?: string; parentPaths: string[] }>();
  const [autoSaveState, setAutoSaveState] = useState<boolean>(defaultAutoSaveState);
  const [permissionMenus, setPermissionMenus] = useState<JSX.Element>();
  const [permissionLoading, setPermissionLoading] = useState<boolean>(false);
  const [releaseLoading, setReleaseLoading] = useState<boolean>(false);

  const [permissionResourceOptions, setPermissionResourceOptions] = useState<API.PermissionOptionsDto[]>();

  /**
   * 处理权限菜单子项
   * @param menus 权限路由
   * @param parentKey 上级key
   * @returns
   */
  const handlePermissionMenuItem = (menus: Partial<PermissionMenu>[], parentKey: string, parentPaths: string[]) => {
    const intlId = parentKey.replace('permission', 'menu').replace('_', '.');

    return menus.filter(t => t.name !== undefined && t.path !== undefined && t.code !== undefined && !t.hideInMenu)
      .map(({ code, name, routes }) => {
        const itemKey = `${parentKey}_${name}`;
        const itemName = intl.formatMessage({
          id: `${intlId}.${name}`,
        });

        const pageFunctions: API.PermissionDto[] = [];
        const permissionList = PermissionsDefinition[code!] ?? {};
        console.log('pageFunctions-init', code, permissionList);
        for (const k in permissionList) {
          console.log('pageFunctions-init', k, permissionList[k]());
          pageFunctions.push({
            id: (Math.random() * 1000000).toFixed(0),
            code: k,
            name: permissionList[k]()
          })
        }

        // 记录初始数据
        initPermissionData.push({
          code: code!,
          name: itemName,
          parentPaths,
          pageFunctions
        });
        if (routes?.length) {
          console.log('initPermissionData', initPermissionData);
          const subItems = handlePermissionMenuItem(routes, itemKey, [...parentPaths, code!]);
          return (
            <Menu.SubMenu key={code} title={itemName}>
              {subItems}
            </Menu.SubMenu>
          );
        }
        else {
          return (<Menu.Item key={code}>{itemName}</Menu.Item>);
        }
      });
  };

  const handleMenuSwitch = (e: any) => {
    console.log('handleMenuSwitch', e, initPermissionData);
    const { key, keyPath } = e;
    const itemName = initPermissionData.find(t => t.code == key)?.name || key;
    const parentPaths = keyPath.reverse();
    parentPaths.pop(); // 移除数组内的最后一个元素,一般为自身key
    setEditableRowKeys([]);
    setActiveMenuItem({ code: key, name: itemName, parentPaths });
  }

  /**
   * 渲染权限菜单并初始化
   * @returns Menu
   */
  const renderPermissionMenu = () => {
    if (PermissionRoutes.length === 0) {
      message.error('权限菜单配置不存在,您需要将受限路由配置在 "/config/permission.ts" 内.');
      return;
    }
    const { code, name, routes } = PermissionRoutes.filter((t: PermissionMenu) => t.code !== undefined)[0] as PermissionMenu;
    initPermissionData = []; // 重置
    const defaultOpenCode = routes?.length ? code : '';
    const defaultSelectedCode = routes?.length ? routes[0].code! : code;
    const defaultSelectedName = routes?.length ? routes[0].name! : '';
    const defaultParentPaths = [name, defaultSelectedName].filter(c => c != '' || c != null || c != undefined);
    const defaultName = intl.formatMessage({
      id: `menu.${defaultParentPaths.join('.')}`,
    });

    setActiveMenuItem({
      code: defaultSelectedCode!,
      name: defaultName,
      parentPaths: [defaultOpenCode! || defaultSelectedCode!]
    });

    const menuItems = handlePermissionMenuItem(PermissionRoutes, 'permission', []);
    return (
      <Menu
        defaultOpenKeys={[defaultOpenCode!]}
        defaultSelectedKeys={[defaultSelectedCode!]}
        mode="inline"
        onClick={handleMenuSwitch}
      >
        {menuItems}
      </Menu>
    )
  }

  const releasePermissionHandle = async () => {
    console.log('submit_permissionData',
      localPermissionConfig,
      activeMenuItem);
    if (editableKeys.length) {
      return message.warning("您当前还有未保存的数据");
    }

    /**
     * 发布逻辑
     * 向服务器提交当前权限菜单项的完整数据和对应的页面先知标识配置
     */

    // 获取父级节点数据
    let parentNodes: API.PermissionConfigReleaseDto[] = [];
    if (permissionIsInit) { // 初始化后才运行
      parentNodes = localPermissionConfig.reduce((pre: API.PermissionConfigReleaseDto[], cur) => {
        const parentList = initPermissionData.filter(t => cur.parentPaths.includes(t.code));
        parentList.forEach(parent => {
          if (!pre.some(t => t.code == parent.code)) {
            pre.push(parent);
          }
        })
        return pre;
      }, []);
    }

    setPermissionLoading(true);
    setReleaseLoading(true);
    try {
      await releaseConfigure([...localPermissionConfig ?? [], ...parentNodes]);
      setLocalPermissionConfig([]);

      // 初始化逻辑
      if (!permissionIsInit) {
        message.success('初始化成功，您可以开始配置权限了');
        setPermissionIsInit(true);
      }
      else {
        message.success('发布成功');
      }
      actionRef.current?.reload();
    }
    catch { }
    finally {
      setPermissionLoading(false);
      setReleaseLoading(false);
    }
  };

  const handleAutoSaveChange = (e: CheckboxChangeEvent) => {
    setAutoSaveState(e.target.checked);
    localStorage.setItem(localStorageAutoSaveKey, e.target.checked.toString());

  }

  const editableDeleteHandle = async (row: API.PermissionDto) => {
    const { id, code } = row;
    const hasLocal = /^[0-9]*$/.test(id!);
    const localConfig = localPermissionConfig.find(t => t.code == activeMenuItem?.code);
    if (localConfig) {
      if (!hasLocal) localConfig.deleteCodes = [...localConfig.deleteCodes || [], code!];
      const updateFunc = localConfig.pageFunctions?.filter(t => t.id != id);
      localConfig!.pageFunctions = updateFunc;
      setLocalPermissionConfig(localPermissionConfig);
    }
    else {
      const remoteConfig = remotePermissionConfig?.find(t => t.code == activeMenuItem?.code) as API.PermissionConfigReleaseDto;
      remoteConfig!.pageFunctions = [];
      if (!hasLocal) remoteConfig!.deleteCodes = [code!];
      setLocalPermissionConfig([...localPermissionConfig, remoteConfig!]);
    }
    hasEditable = true;
    await actionRef.current?.reload();
  }

  const displayRecoverDeleteControl = (code: string) => {
    const localConfig = localPermissionConfig?.find(t => t.code == activeMenuItem?.code);
    if (localConfig) {
      return localConfig.deleteCodes?.includes(code);
    }
    return false;
  }

  const displayDeleteBtnControl = (code: string) => {
    return permissionIsInit
      && initPermissionData.flatMap(i => i.pageFunctions).filter(t => t?.code == code).length === 0
  }

  const handleRecoverDelete = async (code: string) => {
    const localConfig = localPermissionConfig?.find(t => t.code == activeMenuItem?.code);
    if (localConfig) {
      localConfig.deleteCodes = localConfig.deleteCodes?.filter(t => t != code);

      setLocalPermissionConfig(localPermissionConfig);

      hasEditable = true;
      await actionRef.current?.reload();
    }
  }

  const releasePermissionDisabledControl = () => {
    if (permissionIsInit && (localPermissionConfig.length === 0
      || (localPermissionConfig.flatMap(i => (i.deleteCodes || [])).length === 0
        && localPermissionConfig.flatMap(i => i.pageFunctions).length === 0))) {

      return true;
    }
    return false;
  }

  const displayLastSaveTime = () => {
    const time = localStorage.getItem(localStoragePermissionConfigSaveTimeKey);
    if (autoSaveState && time) {
      return <span><FieldTimeOutlined style={{ fontSize: 16 }} /> 保存时间: {time}</span>
    }
    return;
  }

  // 页面初始化
  useEffect(() => {
    // 获取权限菜单
    setPermissionMenus(renderPermissionMenu());
    // 检查权限是否初始化
    checkPermissionIsInit().then(() => {
      if (defaultAutoSaveState) {
        // 若启用了自动保存则设置本地数据
        setLocalPermissionConfig(defaultLocalPermissionConfig);
      }
      setPermissionIsInit(true);
    }).catch(() => {
      // 第一次运行自动初始化 localPermissionConfig
      const initPermissionConfig = Object.assign(initPermissionData, localPermissionConfig);
      setLocalPermissionConfig(initPermissionConfig);
      console.log('useEffect-initPermissionData', initPermissionData, initPermissionConfig);
      setPermissionIsInit(false);
    }).finally(actionRef.current?.reload);

    // 加载权限资源项
    (async () => {
      const { data } = await getPermissionResource();
      setPermissionResourceOptions(data);
    })();

  }, []);// eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (autoSaveState) {
      localStorage.setItem(localStoragePermissionConfigKey, JSON.stringify(localPermissionConfig))
      if (hasEditable || !releasePermissionDisabledControl()) {
        localStorage.setItem(localStoragePermissionConfigSaveTimeKey, moment().format("YYYY-MM-DD HH:mm:ss"));
        hasEditable = false;
      }
      else if (releasePermissionDisabledControl()) {
        localStorage.removeItem(localStoragePermissionConfigSaveTimeKey);
      }

    } else {
      localStorage.removeItem(localStoragePermissionConfigKey);
      if (releasePermissionDisabledControl()) localStorage.removeItem(localStoragePermissionConfigSaveTimeKey);
    }
  }, [localPermissionConfig, autoSaveState, permissionLoading]);// eslint-disable-line react-hooks/exhaustive-deps

  const resourcesFilter = (inputValue: string, path: API.PermissionOptionsDto[]) => {
    return path.some(option => option.name!.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
  }

  const columns: ProColumns<API.PermissionDto>[] = [
    {
      title: '序号',
      dataIndex: 'index',
      valueType: 'index',
      width: 80,
    },
    {
      title: '标识码',
      dataIndex: 'code',
      formItemProps: () => {
        return {
          rules: [{ required: true, message: '标识码为必填项' }],
        };
      },
      editable: (text, record) => {
        console.log('editable', record.id);
        return /^[0-9]*$/.test(record.id!) && permissionIsInit;
      },
      search: false
    },
    {
      title: '名称',
      dataIndex: 'name',
      formItemProps: () => {
        return {
          rules: [{ required: true, message: '名称为必填项' }],
        };
      },
      search: false
    },
    {
      title: '关联资源Id',
      dataIndex: 'dependentResources',
      search: false,
      valueType: 'cascader',
      fieldProps: {
        options: permissionResourceOptions,
        fieldNames: {
          label: 'name',
          value: 'code'
        },
        multiple: true,
        placeholder: '可选配一个或多个模块关联的资源',
        showSearch: {
          filter: resourcesFilter
        }
      },
      ellipsis: true,
      render: (_, entity: API.PermissionDto) => {
        const dependentResources = entity.dependentResources ?? localPermissionConfig.flatMap(m => m.pageFunctions).find(f => f?.code === entity.code)?.dependentResources;

        if (dependentResources && dependentResources.length) {
          if (dependentResources.length > 1) {
            return (<Popover
              content={<Space direction="vertical" key="dependentResources">{dependentResources.map(m => (<Tag key={`dr_${m.join('_')}`} color="#108ee9">{m.join('_')}</Tag>))}</Space>} title={`${entity.name} - 关联资源列表`} trigger="hover">
              <span style={{
                color: '#909399'
              }}>已选择 {dependentResources.length} 个</span>
            </Popover>);
          }
          else {
            const resourceId = dependentResources[0].join('_');
            return (<Tag key={`dr_${resourceId}`} color="#108ee9">{resourceId}</Tag>)
          }

        }
        else {
          return '-';
        }
      }
    },
    {
      title: '操作',
      valueType: 'option',
      width: 150,
      render: (text, record, _, action) => [
        (!displayRecoverDeleteControl(record.code!) &&
          <a
            key="editable"
            onClick={() => {
              action?.startEditable?.(record.id!);
            }}
          >
            编辑
          </a>)
        ,
        (!displayRecoverDeleteControl(record.code!) && displayDeleteBtnControl(record.code!) &&
          <Popconfirm
            key="delete"
            title="删除此行?"
            onConfirm={() => editableDeleteHandle(record)}
            okText="确定"
            cancelText="取消"
          >
            <a href="#">
              删除
            </a>
          </Popconfirm>),
        (displayRecoverDeleteControl(record.code!) && displayDeleteBtnControl(record.code!) &&
          <a style={{ color: 'red' }} key="recoverDelete"
            onClick={() => handleRecoverDelete(record.code!)}>撤销删除</a>)
      ],
    },
  ];

  return (
    <PageContainer className={styles.main}
      breadcrumbRender={false}
      header={{
        extra: [
          <Button key="releasePermission" loading={releaseLoading} type="primary" disabled={releasePermissionDisabledControl()} icon={<RocketOutlined rotate={45} />}
            onClick={releasePermissionHandle}>
            {permissionIsInit ? "发布配置" : "初始化"}
          </Button>
        ]
      }}
      content={<Text key="warning_info" type="warning">配置完成后需要发布才能生效</Text>}
    >
      <EditableProTable<API.PermissionDto>
        columns={columns}
        loading={permissionLoading}
        actionRef={actionRef}
        rowKey="id"
        params={{
          key: activeMenuItem?.code
        }}
        request={(params: any) => {
          console.log('requestParams', params, localPermissionConfig);
          setPermissionLoading(true);
          return getPermissionConfigure({
            key: params.key
          }).then(result => {
            const { data: remoteData } = result;
            setRemotePermissionConfig(remoteData!);
            // 获取本地数据
            const localData = localPermissionConfig.filter(t => t.code == params.key)
              .flatMap(i => i.pageFunctions || []);
            // 远程数据selectMany
            const remotePageFuncs = remoteData?.flatMap(i => i.pageFunctions || []);
            // 合并已定义的数据
            const defineds = remotePageFuncs?.reduce((pre: API.PermissionDto[], cur: API.PermissionDto) => {
              if (pre.every(s => s.code !== cur.code)) {
                pre.push(cur);
              }
              return pre;
            }, localData);
            // 与预设数据比较
            let localConfig = localPermissionConfig.find(t => t.code == activeMenuItem?.code);
            const initModule = initPermissionData.find(f => f.code === params.key);
            const initPageFunc = initModule?.pageFunctions;

            if (!localConfig && defineds?.length === 0) {
              localConfig = {
                ...activeMenuItem!,
                pageFunctions: []
              }
              localPermissionConfig.push(localConfig);
            }

            const list = initPageFunc?.reduce((pre: API.PermissionDto[], cur: API.PermissionDto) => {
              if (pre.every(s => s.code !== cur.code)) {
                pre.push(cur);
                if (!localConfig) {
                  localConfig = {
                    ...activeMenuItem!,
                    pageFunctions: []
                  }
                  localPermissionConfig.push(localConfig);
                }
                localConfig?.pageFunctions?.push(cur);
              }
              return pre;
            }, defineds!);
            if (permissionIsInit) setLocalPermissionConfig(localPermissionConfig);
            // 输出合并后的内容
            return {
              data: list,
              success: true,
            };
          }).finally(() => setPermissionLoading(false));
        }}
        search={{ filterType: "light" }}
        pagination={false}
        tableRender={(_, dom) => (
          <div
            style={{
              display: 'flex',
              width: '100%',
              pointerEvents: permissionLoading ? "none" : "unset"
            }}
          >
            {permissionMenus}
            <div
              style={{
                flex: 1,
              }}
            >
              {dom}
            </div>
          </div>
        )}
        headerTitle="配置"
        tooltip="页面内的受限功能的管理"
        toolBarRender={() => [
          permissionIsInit && displayLastSaveTime(),
          permissionIsInit && <Checkbox checked={autoSaveState} onChange={handleAutoSaveChange}>自动保存</Checkbox>,
        ]}
        editable={{
          editableKeys,
          onSave: async (rowKey, data, row) => {
            console.log('onSave', rowKey, data, row);
            // 针对dependentResources的处理
            //permissionResourceOptions
            let handleDependentResources = data.dependentResources?.filter(t => t.length === 2);
            data.dependentResources?.filter(t => t.length === 1)
              .forEach((dr) => {
                if (Array.isArray(dr) && dr.length === 1) {
                  const handleResult = permissionResourceOptions?.find(f => f.code === dr[0])?.children?.map(m => ([dr[0], m.code!]));
                  handleDependentResources = handleDependentResources?.concat([...handleResult!]);
                }
              });
            // 更新值
            data.dependentResources = handleDependentResources;
            console.log('handleDependentResources', data);

            const localConfig = localPermissionConfig.find(t => t.code == activeMenuItem?.code);
            if (localConfig) {
              const update = localConfig.pageFunctions?.find(t => t.id == data.id);
              if (update) {
                update.code = data.code;
                update.name = data.name;
                update.dependentResources = data.dependentResources;
              }
              else {
                localConfig.pageFunctions = [...localConfig.pageFunctions || [], data];
              }
              setLocalPermissionConfig(localPermissionConfig);
            }
            else {
              setLocalPermissionConfig([...localPermissionConfig, {
                ...activeMenuItem!,
                pageFunctions: [data],
              }]);
            }
            hasEditable = true;
          },
          onDelete: async (key, row) => {
            console.log(`onDelete_${row.index}`, key, row);
            editableDeleteHandle(row);
          },
          onCancel: async (key) => {
            console.log(`OnCancel:${key}`);
            await actionRef.current?.reload();
          },
          onChange: setEditableRowKeys,
          actionRender: (row, config, defaultDom) => [defaultDom.save, defaultDom.cancel]
        }}
        recordCreatorProps={permissionIsInit ? {
          position: 'bottom',
          newRecordType: 'dataSource',
          record: () => ({ id: (Math.random() * 1000000).toFixed(0) })
        } : false}
      />
    </PageContainer>
  );
}

export default PermissionConfig;
